iT邦幫忙

2022 iThome 鐵人賽

DAY 28
0
自我挑戰組

laravel+vue 學習系列 第 28

Day28. 帳號授權與角色

  • 分享至 

  • xImage
  •  

一、哪裡可以定義授權(ALC:access control list)

  1. 使用 Gate 靜態介面
  2. controller
  3. User model 內
  4. middleware
  5. blade 指令

二、定義授權規則(ability)

  1. AuthServiceProvider boot() 內設定
    // 第一個參數為規則名稱
    // 第二個參數為一個可以回傳 boolean 的 closure
    // closure 第一個參數為 user 實例, 第二個參數以後為要驗證的資料(可以多個)
    Gate::('update-product', function($user, $product) {
        // ... 回傳 boolean
        return $user->id === $product->user_id;
    });
  1. policy
  • 當要檢查存取控制的為 Eloquent model 可以設定 policy 控制資源的存取
  • 建立 policy
    php artisan make:policy ProductPolicy
  • 設定 policy
    class ProductPolicy {
        public function update($user, $product) {
            return $user->id == $product->user-id;
        }
        
        // 可以設定 before() 覆寫其他權限
        public function before($user, $ability) {
            if( $user->isAdmin() ) {
                return true;
            }
        }
    }
  • 註冊
    // 於 AuthServiceProvider 
    class AuthServiceProvider  extends ServiceProvider {
        protected $policies = [
            Product::class => ProductPolicy::class
        ];
    }

三、檢查授權

  1. 設定資源 Gate
    // 相對應於路由 product.view、 product.create、 product.update、product.delete
    Gate::resource('product', 'App\Policies\ProductPolicy');
  1. middleware 授權檢查
    // middleware 設定第一個為要執行的規則名稱, 第二個是物件的 id 
    // 若要檢查的並不是實例, 可以將 id 替換成 Class e.g. App\Models\Product
    Route::get('product/{id}/edit', functoin(){
        // ... 修改商品
    })->middleware('can:edit,id');
  1. Controller 授權檢查

    • 在 App\Http\Controllers\Controller 匯入 AuthorizesRequests 特徵, 會提供三種授權方法
      • authorize(): 使用當下登入的 user 進行驗證
          public function edit(Product $product) {
              // 當失敗時會回傳 403 並退出程式
              $this->authorize('update-product', $product);
              return view('product.edit', ['product' => $product]);
          }
      
      • authorizForUser(): 可以切換不同的user 進行驗證, 要傳入 user 實例
          // 可以切換使用非當下登入 user
          $this->authorizeForUser($user, 'update-product', $product);
      
      • authorizeResource(): 當 Controller 為 RESTful 時, 可在建構式內設定, 會對應到 create, update ... 等方法
          class ProductController extends Controller {
              public function __construct() {
                  // 設定完後可以移除其他 function 內的 authorize 驗證
                  $this->authorizeResource(Product::class);
              }
          }
      
  2. 用戶實例授權檢查

  • User 類別匯入 Authorizable 特徵, 會有三種方法
    • can(): 可以執行某個動作( function )
    • cant(): 檢查不能做某個動作( function )
    • cannot(): 同 cant
  1. Blade 指令檢查
    @can('edit-product', $product)
        <a href="{{ route('edit-product', ['product' => $product->id]) ">修改</a>
    @endcan
  1. 攔截檢查
  • 當有超級用戶可以操錯所有動作時, 可以使用 before() 方法來檢查, 在執行其他檢查前執行, 並依情況複寫權限
    // 可在 AuthServiecProdvider 指定
    // $ability 為規則的字串名稱, 可用此來區隔要執行的檢查
    Gate::before(function( $user, $ability ) {
        if ( $user->isOwner() ) {
            return true;
        }
    });
  1. policy 檢查
    // 使用 Gate 靜態介面
    // 此時會呼叫 ProductPolicy 內的 update() 方法檢查
    if(Gate::denies('update', $product)) {
        abort(403);
    }
    
    // 使用 user 檢查
    if( $user->can('update', $product)) {
        // 執行要做的動作
    }
    
    // 使用全域方法 policy() 取回一個 policy 實例並執行他的方法
    if(policy($product)->update($user, $product)) {
        // 執行要做的動作
    }

上一篇
Day27. API 身分驗證 ( OAuth )
下一篇
Day29. Laravel Job
系列文
laravel+vue 學習32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言